using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OpenComposite.EII.Repository;
using WeifenLuo.WinFormsUI.Docking;
using System.Xml;
using System.IO;

namespace OpenComposite.EII.Designer.SCA
{
	public partial class FormSelectOperations : DockContent
	{
		#region Initialization
		public FormSelectOperations(IServiceProvider serviceProvider)
		{
			_serviceProvider = serviceProvider;

			InitializeComponent();

			init();
		}
		private void init()
		{
			this.DialogResult = DialogResult.Cancel;

			this.StartPosition = FormStartPosition.CenterScreen;
			this.DockAreas = DockAreas.Float;
			this.ShowHint = DockState.Float;
			this.TabText = "Capabilities";

			dgvOperations.AutoGenerateColumns = false;

			_operationsSelected = new List<Operation>();
		}
		#endregion

		#region Public Members

		#region Events
		#endregion

		#region Properties
		public bool ReadOnly
		{
			get { return _bReadonly; }
			set {
				if ( _bReadonly != value ) {
					_bReadonly = value;
					dgvOperations.AllowDrop = !_bReadonly;
				}
			}
		}
		public bool MultiSelect
		{
			get { return _bMultiSelect; }
			set { _bMultiSelect = value; }
		}
		public Operation[] Operations
		{
			get { return _operations.ToArray(); }
		}
		public Operation[] SelectedOperations
		{
			get { return _operationsSelected.ToArray(); }
		}
		#endregion

		#region Methods

		public void Show(List<Operation> operations)
		{
			fillList(operations);
			this.Show();
		}
		public void Show(List<Operation> operations, DockPanel dockPanel)
		{
			fillList(operations);
			this.Show(dockPanel);
			//this.Show();
		}
		public DialogResult ShowDialog(List<Operation> operations)
		{
			fillList(operations);
			return base.ShowDialog();
		}

		#endregion

		#endregion

		protected override object GetService(Type service)
		{
			if ( _serviceProvider != null )
				return _serviceProvider.GetService(service);
			else
				return base.GetService(service);
		}

		#region Private Members

		#region Variables
		private bool _bReadonly = false;
		private bool _bMultiSelect = true;
		private DataGridViewCheckBoxCell _lastCheckedCell = null;

		private RepositoryItemBase _parentItem = null;
		private List<Operation> _operations = null;
		private List<Operation> _operationsSelected = null;
		private IServiceProvider _serviceProvider;
		#endregion

		#region Methods
		private void fillList(RepositoryItemBase parentItem)
		{
			_parentItem = parentItem;
			_operations.Clear();
			_operations = null;

			DataTable dt = Global.Data.GetRepositoryHierarchyChildRepositoryList(parentItem, ItemType.Operation);

			colName.DataPropertyName = "operation_nm";
			colInputXsd.DataPropertyName = "operation_input_bobj_nm";
			colOutputXsd.DataPropertyName = "operation_output_bobj_nm";
			colDescription.DataPropertyName = "operation_desc";

			dgvOperations.DataSource = dt;
		}
		private void fillList(List<Operation> operations)
		{
			_parentItem = null;
			_operations = new List<Operation>(operations);

			colName.DataPropertyName = "Name";
			colInputXsd.DataPropertyName = "InputBusinessObjectName";
			colOutputXsd.DataPropertyName = "OutputBusinessObjectName";
			colDescription.DataPropertyName = "Description";

			dgvOperations.DataSource = _operations;
		}
		private void addOperation(Operation operation)
		{
			if ( _parentItem != null ) {
				throw new NotImplementedException();
			} else if ( _operations != null ) {
				_operations.Add(operation);
				fillList(_operations);
			}
		}
		private void deleteOperation(Operation operation)
		{
			if ( _parentItem != null ) {
				throw new NotImplementedException();
			} else if ( _operations != null ) {
				_operations.Remove(operation);
				fillList(_operations);
			}
		}
		private Operation getOperation(int indexRow)
		{
			if ( indexRow < 0 || indexRow >= dgvOperations.RowCount )
				return null;

			Operation op = null;
			object obj = dgvOperations.Rows[indexRow].DataBoundItem;
			if ( obj is DataRow ) {
				throw new NotImplementedException();
			} else if ( obj is Operation ) {
				op = (Operation)obj;
			}
			return op;
		}
		#endregion

		#region Event Handler
		private void dgvOperations_CellContentClick(object sender, DataGridViewCellEventArgs e)
		{
			if ( e.RowIndex < 0 )
				return;
			if ( e.ColumnIndex == colInputXsd.Index || e.ColumnIndex == colOutputXsd.Index ) {

				formXmlViewer frmXml = new formXmlViewer();
				Operation op = getOperation(e.RowIndex);
				XmlDocument xd = new XmlDocument();
				XmlWriterSettings settings = new XmlWriterSettings();
				settings.OmitXmlDeclaration = true;
				if ( e.ColumnIndex == colInputXsd.Index && op.InputSchema != null ) {
					// Input Schema column
					using ( StringWriter sw = new StringWriter() )
					using ( XmlWriter xw = XmlWriter.Create(sw, settings) ) {
						op.InputSchema.Write(xw);
						xw.Flush();
						xd.LoadXml(sw.ToString());
					}
				} else if ( e.ColumnIndex == colOutputXsd.Index && op.OutputSchema != null ) {
					// Output Schema column
					using ( StringWriter sw = new StringWriter() )
					using ( XmlWriter xw = XmlWriter.Create(sw, settings) ) {
						op.OutputSchema.Write(xw);
						xw.Flush();
						xd.LoadXml(sw.ToString());
					}
				}
				frmXml.XmlDocument = xd;
				frmXml.ShowDialog();
			} else if ( e.ColumnIndex == colSelect.Index ) {
				DataGridViewRow row = dgvOperations.Rows[e.RowIndex];
				DataGridViewCheckBoxCell cell = row.Cells[e.ColumnIndex] as DataGridViewCheckBoxCell;
				if ( cell != null ) {
					if ( _operationsSelected.Contains((Operation)row.DataBoundItem) ) {
						_operationsSelected.Remove((Operation)row.DataBoundItem);
						cell.Value = false;
						if ( _lastCheckedCell == cell ) {
							_lastCheckedCell = null;
						}
					} else {
						cell.Value = true;
						if ( !this.MultiSelect ) {
							_operationsSelected.Clear();
							if ( _lastCheckedCell != null && !this.MultiSelect ) {
								_lastCheckedCell.Value = false;
							}
							_lastCheckedCell = cell;
						}
						_operationsSelected.Add((Operation)row.DataBoundItem);
					}
				}
			}
		}

		#region Drag & Drop
		private void dgvOperations_DragDrop(object sender, DragEventArgs e)
		{
			TreeNode tn = e.Data.GetData(typeof(TreeNode)) as TreeNode;
			// if not dragging an Operation object
			if ( tn == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			BusinessObject bo = tn.Tag as BusinessObject;
			if ( bo == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			Point ptClient = dgvOperations.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvOperations.HitTest(ptClient.X, ptClient.Y);
			Operation op = getOperation(hti.RowIndex);
			if ( op == null )
				return;
			// mouse over 'Input Schema' or 'Output Schema' column?
			if ( hti.Type == DataGridViewHitTestType.Cell ) {
				if ( hti.ColumnIndex == colInputXsd.Index ) {
					op.InputSchema = bo.Schema;
				} else if ( hti.ColumnIndex == colOutputXsd.Index ) {
					op.OutputSchema = bo.Schema;
				}
				fillList(_operations);
			}
		}

		private void dgvOperations_DragEnter(object sender, DragEventArgs e)
		{

		}

		private void dgvOperations_DragLeave(object sender, EventArgs e)
		{

		}

		private void dgvOperations_DragOver(object sender, DragEventArgs e)
		{
			TreeNode tn = e.Data.GetData(typeof(TreeNode)) as TreeNode;
			// if not dragging an Operation object
			if ( tn == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			BusinessObject bo = tn.Tag as BusinessObject;
			if ( bo == null ) {
				// drop not allowed
				e.Effect = DragDropEffects.None;
				return;
			}
			Point ptClient = dgvOperations.PointToClient(new Point(e.X, e.Y));
			DataGridView.HitTestInfo hti = dgvOperations.HitTest(ptClient.X, ptClient.Y);
			// mouse over 'Input Schema' or 'Output Schema' column?
			if ( hti.Type == DataGridViewHitTestType.Cell &&
				 ( hti.ColumnIndex == colInputXsd.Index || hti.ColumnIndex == colOutputXsd.Index ) ) {
				e.Effect = DragDropEffects.Move;
			} else {
				e.Effect = DragDropEffects.None;
			}
		}

		private void dgvOperations_GiveFeedback(object sender, GiveFeedbackEventArgs e)
		{

		}

		private void dgvOperations_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
		{

		}
		#endregion

		private void contextMain_Opening(object sender, CancelEventArgs e)
		{
			if ( this.ReadOnly )
				e.Cancel = true;
		}
		private void dgvOperations_MouseDown(object sender, MouseEventArgs e)
		{
		}

		private void tsmiAddNewOp_Click(object sender, EventArgs e)
		{
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			if ( repSvc == null )
				throw new NullReferenceException("RepositoryService not available.");

			bool bSaveContinue;
			do {
				Operation op = repSvc.GetItem(ItemType.Operation, true, 0, true, out bSaveContinue) as Operation;
				if ( op != null )
					addOperation(op);
			} while ( bSaveContinue );
		}
		private void tsmiDeleteOp_Click(object sender, EventArgs e)
		{
			if ( dgvOperations.SelectedRows.Count <= 0 )
				return;
			object objsel = dgvOperations.SelectedRows[0].DataBoundItem;
			if ( objsel is DataRow ) {
				throw new NotImplementedException();
			} else if ( objsel is Operation ) {
				deleteOperation((Operation)objsel);
			}
		}

		private void tsbtnOK_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.OK;
			this.Close();
		}
		private void tsbtnCancel_Click(object sender, EventArgs e)
		{
			this.DialogResult = DialogResult.Cancel;
			this.Close();
		}

		#endregion



		#endregion

	}
}